﻿using JESAI.HttpRequestMonitor.Core.Abstracts;
using JESAI.HttpRequestMonitor.Options;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Text;

namespace JESAI.HttpRequestMonitor.Builders
{
    internal class DefaultRequestModelBuilder : BaseRequestModelBuilder
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="modelCreator"></param>
        /// <param name="options"></param>
        public DefaultRequestModelBuilder(IModelCreator modelCreator, IOptions<HttpRequestMonitorOptions> options) : base(modelCreator, options)
        {

        }

        protected override (IRequestModel, IRequestDetailModel) Build(HttpContext context, IRequestModel requestModel, string path)
        {
            if (string.IsNullOrWhiteSpace(Options.Node))
            {
                Options.Node = "Default";
            }

            requestModel.Node = Options.Node.Substring(0, 1).ToUpper() + Options.Node.Substring(1).ToLower();
            requestModel.Route = path.GetRoute();

            IRequestDetailModel requestDetailModel = GetRequestDetailModel(context, requestModel);

            requestDetailModel.RequestId = requestModel.Id = Activity.Current.SpanId.ToHexString();

            requestModel.ParentId = Activity.Current.ParentId == null ? string.Empty : Activity.Current.ParentSpanId.ToHexString();

            return (requestModel, requestDetailModel);
        }

        private IRequestDetailModel GetRequestDetailModel(HttpContext context, IRequestModel requestModel)
        {
            IRequestDetailModel requestDetailModel = ModelCreator.CreateRequestDetailModel();

            if (context.Request != null)
            {
                requestDetailModel.Id = Guid.NewGuid().ToString();
                requestDetailModel.RequestId = requestModel.Id;

                //获取会话Cookies
                Dictionary<string, string> cookies = context.Request.Cookies.ToList().ToDictionary(x => x.Key, x => x.Value);
                if (cookies != null && cookies.Count > 0)
                {
                    requestDetailModel.Cookie = JsonConvert.SerializeObject(cookies);
                }

                Dictionary<string, string> headers = context.Request.Headers.ToList().ToDictionary(x => x.Key, x => string.Join(",", x.Value));

                if (headers != null && headers.Count > 0)
                {
                    requestDetailModel.RequestHeader = JsonConvert.SerializeObject(headers);
                }

                if (context.Items.ContainsKey(SysConst.HttpRequestMonitorGlobalException))
                {
                    Exception ex = context.Items[SysConst.HttpRequestMonitorGlobalException] as Exception;

                    if (ex != null)
                    {
                        requestDetailModel.ErrorMessage = ex.Message;
                        requestDetailModel.ErrorStackTrace = ex.StackTrace;
                    }

                    context.Items.Remove(SysConst.HttpRequestMonitorGlobalException);
                }

                if (context.Items.ContainsKey(SysConst.HttpRequestMonitorRequestBody))
                {
                    string requestBody = context.Items[SysConst.HttpRequestMonitorRequestBody] as string;

                    if (!string.IsNullOrWhiteSpace(requestBody))
                    {
                        requestDetailModel.RequestBody = requestBody;
                    }

                    context.Items.Remove(SysConst.HttpRequestMonitorRequestBody);
                }

                if (context.Items.ContainsKey(SysConst.HttpRequestMonitorResponseBody))
                {
                    string responseBody = context.Items[SysConst.HttpRequestMonitorResponseBody] as string;

                    if (!string.IsNullOrWhiteSpace(responseBody))
                    {
                        requestDetailModel.ResponseBody = responseBody;
                    }

                    context.Items.Remove(SysConst.HttpRequestMonitorResponseBody);
                }

                requestDetailModel.Scheme = context.Request.Scheme;
                requestDetailModel.CreateTime = context.Items[SysConst.ActiveTraceCreateTime].ToDateTime();
                requestDetailModel.QueryString = context.Request.QueryString.Value;
            }

            return requestDetailModel;
        }
    }
}
